package rtool

import (
	"encoding/base64"
	"encoding/hex"
	"errors"
	"fmt"
	"math/big"
	"strings"
)

// Base64Decode base64解码
func Base64Decode(content string) (decodeString []byte, err error) {
	decodeString, err = base64.StdEncoding.DecodeString(content)
	if err == nil {
		return
	}
	decodeString, err = base64.RawStdEncoding.DecodeString(content)
	if err == nil {
		return
	}
	decodeString, err = base64.URLEncoding.DecodeString(content)
	if err == nil {
		return
	}
	decodeString, err = base64.RawURLEncoding.DecodeString(content)
	return
}

// NumberToBase 转换进制
// number：2~36进制的数字
// base：传入的number是多少进制的数字
// outBase：输出结果为多少进制的
func NumberToBase(number string, base int, outBase int) (string, error) {
	val, bl := (&big.Int{}).SetString(number, base)
	if false == bl {
		return "", errors.New(fmt.Sprint("传入的", number, "不是", base, "进制数据。"))
	}
	return val.Text(outBase), nil
}

// Base64ToBase base64解码后转成其它进制
// base64Content base64的内容
// outBase：输出结果为多少进制的，2~36
func Base64ToBase(base64Content string, outBase int) (string, error) {
	decodeString, err := Base64Decode(base64Content)
	if err != nil {
		return "", err
	}
	hexStr := hex.EncodeToString(decodeString)
	if outBase == 16 {
		return hexStr, nil
	}
	return NumberToBase(hexStr, 16, outBase)
}

// NumberToBase64 数字转成十六进制，再转成 base64 。
func NumberToBase64(number int64) (string, error) {
	base, err := NumberToBase(fmt.Sprintf("%v", number), 10, 16)
	if err != nil {
		return "", err
	}
	bs, err := hex.DecodeString(base)
	if err != nil {
		return "", err
	}
	return base64.StdEncoding.EncodeToString(bs), nil
}

// Base64ImageCut base64图片切割出图片类型和图片内容
func Base64ImageCut(base64Content string) (string, string, error) {
	if len(base64Content) < 10 {
		return "", "", errors.New("base64编码内容过短")
	}
	before, after, found := strings.Cut(base64Content, "base64,")
	if !found {
		return "", "", errors.New("base64编码前面必须带data:image")
	}
	return before, after, nil
}

// Base64ImageParse base64图片切割出图片类型和图片内容
func Base64ImageParse(base64Content string) (string, []byte, error) {
	if len(base64Content) < 10 {
		return "", nil, errors.New("base64编码内容过短")
	}
	before, after, found := strings.Cut(base64Content, "base64,")
	if !found {
		return "", nil, errors.New("base64编码前面必须带data:image")
	}
	imgContent, err := Base64Decode(after)
	if err != nil {
		return "", nil, err
	}
	return before, imgContent, nil
}

// Base64ImageEncode 编码成base64图片的字符串
func Base64ImageEncode(base64Content []byte, imgType string) (string, error) {
	if len(base64Content) < 10 {
		return "", errors.New("图片内容过短")
	}
	encodeToString := base64.StdEncoding.EncodeToString(base64Content)
	imgType = strings.TrimLeft(imgType, ".")
	switch imgType {
	case "jpg":
		return "data:image/jpeg;base64," + encodeToString, nil
	case "jpeg":
		return "data:image/jpeg;base64," + encodeToString, nil
	case "png":
		return "data:image/png;base64," + encodeToString, nil
	case "gif":
		return "data:image/gif;base64," + encodeToString, nil
	case "webp":
		return "data:image/webp;base64," + encodeToString, nil
	case "bmp":
		return "data:image/bmp;base64," + encodeToString, nil
	case "tiff":
		return "data:image/tiff;base64," + encodeToString, nil
	default:
		return encodeToString, errors.New("不支持的来源格式")
	}
}

// Base64ImageToPng base64图片转成png
func Base64ImageToPng(base64Content string) ([]byte, error) {
	before, imgContent, err := Base64ImageParse(base64Content)
	if err != nil {
		return nil, err
	}
	switch before {
	case "data:image/webp;":
		return ToPNG(imgContent, "webp")
	case "data:image/jpeg;":
		return ToPNG(imgContent, "jpeg")
	case "data:image/gif;":
		return ToPNG(imgContent, "gif")
	case "data:image/bmp;":
		return ToPNG(imgContent, "bmp")
	case "data:image/tiff;":
		return ToPNG(imgContent, "tiff")
	case "data:image/png;":
		return imgContent, nil
	default:
		return nil, errors.New("暂不支持该格式")
	}
}

// Base64ImageToJPEG base64图片转成jpeg
func Base64ImageToJPEG(base64Content string) ([]byte, error) {
	before, imgContent, err := Base64ImageParse(base64Content)
	if err != nil {
		return nil, err
	}
	switch before {
	case "data:image/webp;":
		return ToJPEG(imgContent, "webp")
	case "data:image/png;":
		return ToJPEG(imgContent, "png")
	case "data:image/gif;":
		return ToJPEG(imgContent, "gif")
	case "data:image/bmp;":
		return ToJPEG(imgContent, "bmp")
	case "data:image/tiff;":
		return ToJPEG(imgContent, "tiff")
	case "data:image/jpeg;":
		return imgContent, nil
	default:
		return nil, errors.New("暂不支持该格式")
	}
}
